﻿/*++ BUILD Version: 0001    // Increment this if a change has global effects

Copyright (c).  All rights reserved.

Module Name:

        TString.h 

Abstract:

        TString为自定义字符串类型，支持'ANSI与'UNICODE'字符混合操作

        设计初衷：
            TString对象相当于字符串容器，支持不同字符类型的相关操作：赋值、相加、比较...，同时可以很多返回常用的字符串类型

Revision History:

--*/
#ifndef _TSTRING_H_H_
#define _TSTRING_H_H_
#include <string>
#include <atlstr.h>
using namespace std;

#ifndef CP_UTF8
#define CP_UTF8  65001
#endif
#ifndef CP_ACP
#define CP_ACP   0
#endif
#define __TSTRING_VALUE(_T_) basic_string<_T_, std::char_traits<_T_>, allocator<_T_> >


/*++
 * class _TStrBase
 * 提供TString内部使用的转换基类，外部使用者不必关心
 --*/
class _TStrBase {
protected:
    static const wchar_t* AnsiToUnicode (
        /*__in*/ unsigned int CodePage, 
        /*__in*/ const char* pszSrc, 
        /*__out*/ std::wstring &wstrDes
        );
    static const char* UnicodeToAnsi (
        /*__in*/ unsigned int CodePage, 
        /*__in*/ const wchar_t* lpszSrc, 
        /*__out*/ std::string &strDes
        );
    static const char* AnsiToUtf8 (
        /*__in*/ unsigned int CodePage, 
        /*__in*/ const char* pszSrc, 
        /*__out*/ std::string &strUtf8
        );
    static const char* Utf8ToAnsi (
        /*__in*/ unsigned int CodePage, 
        /*__in*/ const char* pszUtf8, 
        /*__out*/ std::string &strAnsi
        );
    static const char* TSB_ToUpper (
        /*__inout*/ std::string &strUpper
        );
    static const wchar_t* TSB_ToUpper (
        /*__inout*/ std::wstring &strUpper
        );
    static const char* TSB_ToLower (
        /*__inout*/ std::string &strLower
        );
    static const wchar_t* TSB_ToLower (
        /*__inout*/ std::wstring &strLower
        );
    static const char* __cdecl TSB_FormatA (
        /*__out*/ string& strResult, 
        /*__in*/ const char* pszFormat, 
        /*__in*/ va_list argList
        );
    static const wchar_t* __cdecl TSB_FormatW (
        /*__out*/ wstring& strResult, 
        /*__in*/ const wchar_t* pszFormat, 
        /*__in*/ va_list argList
        );
    static unsigned int TSB_Find (
        /*__in*/ const string& strDes, 
        /*__in*/ const char* lpszSrc, 
        /*__in*/ const unsigned int& nStartPos, 
        /*__in*/ const bool& bNotCaseSensitive
        );
    static unsigned int TSB_Find (
        /*__in*/ const wstring& strDes, 
        /*__in*/ const wchar_t* lpszSrc, 
        /*__in*/ const unsigned int& nStartPos, 
        /*__in*/ const bool& bNotCaseSensitive
        );
    static unsigned int TSB_Find (
        /*__in*/ const string& strDes, 
        /*__in*/ const char& cSrc, 
        /*__in*/ const unsigned int& nStartPos, 
        /*__in*/ const bool& bNotCaseSensitive
        );
    static unsigned int TSB_Find (
        /*__in*/ const wstring& strDes, 
        /*__in*/ const wchar_t& cSrc, 
        /*__in*/ const unsigned int& nStartPos, 
        /*__in*/ const bool& bNotCaseSensitive
        );
};


/*++
 * class UTFString
 * 该类型用于保存UTF8字符串，TString对UTFString对象的返回或者其他相关操作都会认为是UTF8字符串
 * 如果需要对UTFString对象进行初始化或者赋值操作，请确保操作字符串为UTF8类型
 * UTFString提供UTFString::ToUtf8静态函数，支持'ANSI'与'UNICODE'字符串转化为UTF8类型
 --*/
class UTFString : protected _TStrBase {

public:
    UTFString() {}
    UTFString(const char* psz) {
        this->_utf = psz;
    }
    UTFString(const string &s) {
        this->_utf = s;
    }
    UTFString(const UTFString &utfs) {
        this->_utf = utfs._utf;
    }

    UTFString& operator=(const char* psz) {
        this->_utf = psz;
        return *this;
    }
    UTFString& operator=(const string &s) {
        this->_utf = s;
        return *this;
    }
    UTFString& operator=(const UTFString &utfs) {
        this->_utf = utfs._utf;
        return *this;
    }

    string ToString() { 
        return _utf;
    }

    const char* Data() const {
        return _utf.c_str();
    }

    int Length() const {
        return _utf.length();
    }

    operator string() {
        return ToString();
    }

    operator const char*() const {
        return Data();
    } 

    __inline static string ToUtf8(const char* pszAnsi);
    __inline static string ToUtf8(const wchar_t* pszUnicode);

private:
    string _utf;
};

__inline string UTFString::ToUtf8(const char* pszAnsi) {
    std::string str;
    return AnsiToUtf8(CP_ACP, pszAnsi, str);
}
__inline string UTFString::ToUtf8(const wchar_t* pszUnicode) {
    std::string str;
    return UnicodeToAnsi(CP_UTF8, pszUnicode, str);
}


/*++
 * class TStringBase
 * TString实现
 --*/
template<class T>
class TStringBase : protected _TStrBase
{
public:
    TStringBase(const char& ch) {
        ToIni(this->_s, string(1, ch));
    }
    TStringBase(const wchar_t& ch) {
        ToIni(this->_s, wstring(1, ch));
    }
    TStringBase(const char* str) {
        ToIni(this->_s, str);
    }
    TStringBase(const wchar_t* str) {
        ToIni(this->_s, str);
    }
    TStringBase(const string& str) {
        ToIni(this->_s, str);
    }
    TStringBase(const wstring& str) {
        ToIni(this->_s, str);
    }
    TStringBase(const TStringBase<char>& tstr) {
        ToIni(this->_s, tstr.Object());
    }
    TStringBase(const TStringBase<wchar_t>& tstr) {
        ToIni(this->_s, tstr.Object());
    }
    TStringBase(const UTFString& utf) {
        ToIni(this->_s, ToUnicode((const char*)utf, CP_UTF8));
    }

    TStringBase() {}
    virtual ~TStringBase() {}

    // 值转换函数
    UTFString ToUtf8() {
        return ToAscii(_s.c_str(), CP_UTF8);
    }
    string ToString() {
        return ToAscii(_s.c_str(), CP_ACP);
    }
    wstring ToWstring() {
        return ToUnicode(_s.c_str(), CP_ACP);
    }
//     CStringA ToCStringA() {
//         return ToString().c_str();
//     }
//     CStringW ToCStringW() {
//         return ToWstring().c_str();
//     }

    // 值转换操作符
    operator UTFString() {
        return ToUtf8();
    }
    operator string() {
        return ToString();
    }
    operator wstring() {
        return ToWstring();
    }
//     operator CStringA() {
//         return ToCStringA();
//     }
//     operator CStringW() {
//         return ToCStringW();
//     }

    // 自加函数
    TStringBase& Append(const TStringBase<char>& tstr) {
        ToValue(this->_s, TStringBase<char>(tstr));
        return *this;
    }
    TStringBase& Append(const TStringBase<wchar_t>& tstr) {
        ToValue(this->_s, TStringBase<wchar_t>(tstr));
        return *this;
    }
    TStringBase& Append(const char& ch) {
        ToValue(this->_s, TStringBase<char>( ch ));
        return *this;
    }
    TStringBase& Append(const wchar_t& ch) {
        ToValue(this->_s, TStringBase<wchar_t>( ch ));
        return *this;
    }
    TStringBase& Append(const char* str) {
        ToValue(this->_s, TStringBase<char>(str));
        return *this;
    }
    TStringBase& Append(const wchar_t* str) {
        ToValue(this->_s, TStringBase<wchar_t>(str));
        return *this;
    }
    TStringBase& Append(const string& str) {
        ToValue(this->_s, TStringBase<char>(str));
        return *this;
    }
    TStringBase& Append(const wstring& str) {
        ToValue(this->_s, TStringBase<wchar_t>(str));
        return *this;
    }
    TStringBase& Append(const UTFString& utf) {
        ToValue(this->_s, TStringBase<wchar_t>(ToUnicode((const char*)utf, CP_UTF8).c_str()));
        return *this;
    }

    // 自加操作符
    TStringBase& operator+=(const TStringBase<char>& tstr) {
        return Append(tstr);
    }
    TStringBase& operator+=(const TStringBase<wchar_t>& tstr) {
        return Append(tstr);
    }
    TStringBase& operator+=(const char& ch) {
        return Append(ch);
    }
    TStringBase& operator+=(const wchar_t& ch) {
        return Append(ch);
    }
    TStringBase& operator+=(const char* str) {
        return Append(str);
    }
    TStringBase& operator+=(const wchar_t* str) {
        return Append(str);
    }
    TStringBase& operator+=(const string& str) {
        return Append(str);
    }
    TStringBase& operator+=(const wstring& str) {
        return Append(str);
    }
    TStringBase& operator+=(const UTFString& utf) {
        return Append(utf);
    }

    // 相加
    TStringBase operator+(const TStringBase<char>& tstr) {
        return TStringBase(*this).Append(tstr);
    }
    TStringBase operator+(const TStringBase<wchar_t>& tstr) {
        return TStringBase(*this).Append(tstr);
    }
    // 右值相加
    TStringBase operator+(const char& ch) {
        return TStringBase(*this).Append(ch);
    }
    TStringBase operator+(const wchar_t& ch) {
        return TStringBase(*this).Append(ch);
    }
    TStringBase operator+(const char* str) {
        return TStringBase(*this).Append(str);
    }
    TStringBase operator+(const wchar_t* str) {
        return TStringBase(*this).Append(str);
    }
    TStringBase operator+(const string& str) {
        return TStringBase(*this).Append(str);
    }
    TStringBase operator+(const wstring& str) {
        return TStringBase(*this).Append(str);
    }
    TStringBase operator+(const UTFString& utf) {
        return TStringBase(*this).Append(utf);
    }
    // 左值相加
    friend TStringBase operator+(const char& ch, const TStringBase& tstr) {
        return TStringBase(ch).Append(tstr);
    }
    friend TStringBase operator+(const wchar_t& ch, const TStringBase& tstr) {
        return TStringBase(ch).Append(tstr);
    }
    friend TStringBase operator+(const char* str, const TStringBase& tstr) {
        return TStringBase(str).Append(tstr);
    }
    friend TStringBase operator+(const wchar_t* str, const TStringBase& tstr) {
        return TStringBase(str).Append(tstr);
    }
    friend TStringBase operator+(const string& str, const TStringBase& tstr) {
        return TStringBase(str).Append(tstr);
    }
    friend TStringBase operator+(const wstring& str, const TStringBase& tstr) {
        return TStringBase(str).Append(tstr);
    }
    friend TStringBase operator+(const UTFString& utf, const TStringBase& tstr) {
        return TStringBase(utf).Append(tstr);
    }

    // 赋值
    TStringBase& operator=(const TStringBase<char> &tstr) {
        ToValue(this->_s, TStringBase<char>(tstr), false);
        return *this;
    }
    TStringBase& operator=(const TStringBase<wchar_t> &tstr) {
        ToValue(this->_s, TStringBase<wchar_t>(tstr), false);
        return *this;
    }
    TStringBase& operator=(const char& ch) {
        *this = TStringBase<char>(ch);
        return *this;
    }
    TStringBase& operator=(const wchar_t& ch) {
        *this = TStringBase<wchar_t>(ch);
        return *this;
    }
    TStringBase& operator=(const char* str) {
        *this = TStringBase<char>(str);
        return *this;
    }
    TStringBase& operator=(const wchar_t* str) {
        *this = TStringBase<wchar_t>(str);
        return *this;
    }
    TStringBase& operator=(const string& str) {
        *this = TStringBase<char>(str);
        return *this;
    }
    TStringBase& operator=(const wstring& str) {
        *this = TStringBase<wchar_t>(str);
        return *this;
    }
    TStringBase& operator=(const UTFString& utf) {
        *this = TStringBase<wchar_t>(utf);
        return *this;
    }

    // 比较
    bool operator==(const TStringBase<char> &tstr) {
        return ToCompare(this->_s, TStringBase<char>(tstr));
    }
    bool operator==(const TStringBase<wchar_t> &tstr) {
        return ToCompare(this->_s, TStringBase<wchar_t>(tstr));
    }
    // 右值比较
    bool operator==(const char &ch) {
        return *this == TStringBase<char>( ch );
    }
    bool operator==(const wchar_t &ch) {
        return *this == TStringBase<wchar_t>( ch );
    }
    bool operator==(const char* str) {
        return *this == TStringBase<char>( str );
    }
    bool operator==(const wchar_t* str) {
        return *this == TStringBase<wchar_t>( str );
    }
    bool operator==(const string& str) {
        return *this == TStringBase<char>( str );
    }
    bool operator==(const wstring& str) {
        return *this == TStringBase<wchar_t>( str );
    }
    bool operator==(const UTFString& utf) {
        return *this == TStringBase<wchar_t>( utf );
    }
    // 左值比较
    friend bool operator==(const char &ch, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == ch;
    }
    friend bool operator==(const wchar_t &ch, const TStringBase& tstr) throw() {
        return TStringBase( tstr ) == ch;
    }
    friend bool operator==(const char* str, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == str;
    }
    friend bool operator==(const wchar_t* str, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == str;
    }
    friend bool operator==(const string& str, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == str;
    }
    friend bool operator==(const wstring& str, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == str;
    }
    friend bool operator==(const UTFString& utf, const TStringBase& tstr) throw() {
        return TStringBase(tstr) == utf;
    }

    // 格式化
    void FormatV(const char* pszFormat, va_list argList) {
        *this = TSB_FormatA(string(), pszFormat, argList);
    }
    void FormatV(const wchar_t* pszFormat, va_list argList) {
        *this = TSB_FormatW(wstring(), pszFormat, argList);
    }
    void AppendFormatV(const char* pszFormat, va_list argList) {
        *this += TSB_FormatA(string(), pszFormat, argList);
    }
    void AppendFormatV(const wchar_t* pszFormat, va_list argList) {
        *this += TSB_FormatW(wstring(), pszFormat, argList);
    }
    void Format(const char* pszFormat, ... ) {
        va_list argList;
        va_start(argList, pszFormat);
        FormatV(pszFormat, argList);
        va_end(argList);
    }
    void Format(const wchar_t* pszFormat, ... ) {
        va_list argList;
        va_start(argList, pszFormat);
        FormatV(pszFormat, argList);
        va_end(argList);
    }
    void AppendFormat(const char* pszFormat, ... ) {
        va_list argList;
        va_start(argList, pszFormat);
        AppendFormatV(pszFormat, argList);
        va_end(argList);
    }
    void AppendFormat(const wchar_t* pszFormat, ... ) {
        va_list argList;
        va_start(argList, pszFormat);
        AppendFormatV(pszFormat, argList);
        va_end(argList);
    }

    const T* Data() const {
        return _s.c_str();
    }
    unsigned int Length() const {
        return _s.length();
    }

    bool Empty() {
        Length() == 0;
    }

     const __TSTRING_VALUE(T)& Object() const { 
         return _s;
     }

    // 大小写转换
    void Upper() {
        TSB_ToUpper((__TSTRING_VALUE(T)&)this->Object());
    }
    void Lower() {
        TSB_ToLower((__TSTRING_VALUE(T)&)this->Object());
    }
    TStringBase GetUpper() {
        TStringBase tsb = *this;
        TSB_ToUpper((__TSTRING_VALUE(T)&)tsb.Object());
        return tsb;
    }
    TStringBase GetLower() {
        TStringBase tsb = *this;
        TSB_ToLower((__TSTRING_VALUE(T)&)tsb.Object());
        return tsb;
    }

    // 截取子串
    TStringBase SubStr(const unsigned int& nStartPos, const unsigned int& nConut = -1) {
        return Object().substr(nStartPos>Length()?Length():nStartPos, nConut==-1 ? 
            string::npos : (nConut>Length()-nStartPos ? string::npos : nConut) );
    }
    TStringBase LeftSubStr(const unsigned int& nCount) {
        return SubStr(0, nCount);
    }
    TStringBase RightSubStr(const unsigned int& nCount) {
        return SubStr(nCount > Length() ? 0 : Length()-nCount, -1);
    }

    // 查找子串
    unsigned int Find(const char* pszSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(pszSrc)).c_str(), nStartPos, false);
    }
    unsigned int Find(const wchar_t* pszSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(pszSrc)).c_str(), nStartPos, false);
    }
    unsigned int Find(const char cSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(cSrc)).at(0), nStartPos, false);
    }
    unsigned int Find(const wchar_t cSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(cSrc)).at(0), nStartPos, false);
    }
    unsigned int FindI(const char* pszSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(pszSrc)).c_str(), nStartPos, true);
    }
    unsigned int FindI(const wchar_t* pszSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(pszSrc)).c_str(), nStartPos, true);
    }
    unsigned int FindI(const char cSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(cSrc)).at(0), nStartPos, true);
    }
    unsigned int FindI(const wchar_t cSrc, const unsigned int& nStartPos = 0) {
        return TSB_Find(Object(), ((__TSTRING_VALUE(T))TStringBase(cSrc)).at(0), nStartPos, true);
    }

private:
    string ToAscii(const char* str, const int& cp) {
        return cp == CP_UTF8 ? AnsiToUtf8(cp, str, string()) : _s;
    }
    string ToAscii(const wchar_t* str, const int& cp) {
        std::string strDes;
        return UnicodeToAnsi(cp, str, strDes);
    }
    wstring ToUnicode(const char* str, const int& cp) {
        std::wstring strDes;
        return AnsiToUnicode(cp, str, strDes);
    }
    wstring ToUnicode(const wchar_t* str, const int& cp) {
        return str;
    }

#define _tsb_value(self, cla, tstr, bAppend) self = bAppend ? self+(cla)tstr : (cla)tstr;
    void ToValue(string& str, TStringBase<char>& tstr, const bool& bAppend=true) {
        _tsb_value(str, string, tstr, bAppend);
    }
    void ToValue(string& str, TStringBase<wchar_t>& tstr, const bool& bAppend=true) {
        _tsb_value(str, string, tstr, bAppend);
    }
    void ToValue(wstring& str, TStringBase<char>& tstr, const bool& bAppend=true) {
        _tsb_value(str, wstring, tstr, bAppend);
    }
    void ToValue(wstring& str, TStringBase<wchar_t>& tstr, const bool& bAppend=true) {
        _tsb_value(str, wstring, tstr, bAppend);
    }

    bool ToCompare(const string& str, TStringBase<char>& tstr) {
        return str == (string)tstr;
    }
    bool ToCompare(const string& str, TStringBase<wchar_t>& tstr) {
        return str == (string)tstr;
    }
    bool ToCompare(const wstring& str, TStringBase<char>& tstr) {
        return str == (wstring)tstr;
    }
    bool ToCompare(const wstring& str, TStringBase<wchar_t>& tstr) {
        return str == (wstring)tstr;
    }

    void ToIni(string& str1, const string& str2) {
        str1 = str2;
    }
    void ToIni(string& str1, const  wstring& str2) {
        str1 = ToAscii(str2.c_str(), CP_ACP);
    }
    void ToIni(wstring& str1, const string& str2) {
        str1 = ToUnicode(str2.c_str(), CP_ACP);
    }
    void ToIni(wstring& str1, const wstring& str2) {
        str1 = str2;
    }

private:
    __TSTRING_VALUE(T) _s;
};


typedef TStringBase< char > TStringA;
typedef TStringBase< wchar_t > TStringW;

#if UNICODE
typedef TStringW TString;
#else
typedef TStringA TString;
#endif

#endif // _TSTRING_H_H_